package overun.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import overun.selected.ExcelSelected;
import overun.selected.ExcelSelectedResolve;
import overun.selected.SelectedSheetWriteHandler;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
 
@Slf4j
public class EasyExcelUtil {
 
	/**
	 * 创建即将导出的sheet页（sheet页中含有带下拉框的列）
	 * @param head 导出的表头信息和配置
	 * @param sheetNo sheet索引
	 * @param sheetName sheet名称
	 * @param <T> 泛型
	 * @return sheet页
	 */
	public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName) {
		Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head);
 
		return EasyExcel.writerSheet(sheetNo, sheetName)
			.head(head)
			.registerWriteHandler(new SelectedSheetWriteHandler(selectedMap))
			.build();
	}
 
	/**
	 * 解析表头类中的下拉注解
	 * @param head 表头类
	 * @param <T> 泛型
	 * @return Map<下拉框列索引, 下拉框内容> map
	 */
	private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head) {
		Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();
 
		// getDeclaredFields(): 返回全部声明的属性；getFields(): 返回public类型的属性
		Field[] fields = head.getDeclaredFields();
		for (int i = 0; i < fields.length; i++){
			Field field = fields[i];
			// 解析注解信息
			ExcelSelected selected = field.getAnnotation(ExcelSelected.class);
			ExcelProperty property = field.getAnnotation(ExcelProperty.class);
			if (selected != null) {
				ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
				String[] source = excelSelectedResolve.resolveSelectedSource(selected);
				if (source != null && source.length > 0){
					excelSelectedResolve.setSource(source);
					excelSelectedResolve.setFirstRow(selected.firstRow());
					excelSelectedResolve.setLastRow(selected.lastRow());
					if (property != null && property.index() >= 0){
						selectedMap.put(property.index(), excelSelectedResolve);
					} else {
						selectedMap.put(i, excelSelectedResolve);
					}
				}
			}
		}
		return selectedMap;
	}
 
	public static boolean isIDNumber(String IDNumber) {
		if (IDNumber == null || "".equals(IDNumber)) {
			return false;
		}
		// 定义判别用户身份证号的正则表达式（15位或者18位，最后一位可以为字母）
		String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +
			"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
		//假设18位身份证号码:41000119910101123X  410001 19910101 123X
		//^开头
		//[1-9] 第一位1-9中的一个      4
		//\\d{5} 五位数字           10001（前六位省市县地区）
		//(18|19|20)                19（现阶段可能取值范围18xx-20xx年）
		//\\d{2}                    91（年份）
		//((0[1-9])|(10|11|12))     01（月份）
		//(([0-2][1-9])|10|20|30|31)01（日期）
		//\\d{3} 三位数字            123（第十七位奇数代表男，偶数代表女）
		//[0-9Xx] 0123456789Xx其中的一个 X（第十八位为校验值）
		//$结尾
 
		//假设15位身份证号码:410001910101123  410001 910101 123
		//^开头
		//[1-9] 第一位1-9中的一个      4
		//\\d{5} 五位数字           10001（前六位省市县地区）
		//\\d{2}                    91（年份）
		//((0[1-9])|(10|11|12))     01（月份）
		//(([0-2][1-9])|10|20|30|31)01（日期）
		//\\d{3} 三位数字            123（第十五位奇数代表男，偶数代表女），15位身份证不含X
		//$结尾
		boolean matches = IDNumber.matches(regularExpression);
 
		//判断第18位校验值
		if (matches) {
 
			if (IDNumber.length() == 18) {
				try {
					char[] charArray = IDNumber.toCharArray();
					//前十七位加权因子
					int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
					//这是除以11后，可能产生的11位余数对应的验证码
					String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
					int sum = 0;
					for (int i = 0; i < idCardWi.length; i++) {
						int current = Integer.parseInt(String.valueOf(charArray[i]));
						int count = current * idCardWi[i];
						sum += count;
					}
					char idCardLast = charArray[17];
					int idCardMod = sum % 11;
					if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
						return true;
					} else {
						return false;
					}
 
				} catch (Exception e) {
					e.printStackTrace();
					return false;
				}
			}
			return false;
		}
		return matches;
	}
 
 
	public static  boolean isMobile(String phone){
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		// 验证手机号
		String s2="^[1](([3|5|6|7|8|9][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";
		if(StringUtils.isNotBlank(phone)){
			p = Pattern.compile(s2);
			m = p.matcher(phone);
			b = m.matches();
		}
		return b;
	}
 
}